package com.kcwx.framework.websocket;

import java.io.IOException;
import java.util.concurrent.ConcurrentMap;

import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

/**
 * @author HFL
 * @date 2022/5/16 15:17 Websocket应用实现: 1.建立连接，连接放入连接池 2.关闭连接，连接移出连接池
 *       3.接收客户端发送的消息，并做出相应处理 4.注入业务层的service
 *       [注意：Spring管理的Bean是单例模式的，而WebSocket不是单例，注入时需要处理一下] 5.异常处理，连接移除连接池
 */
@Component
@ServerEndpoint("/webSocket/{clientId}")
public class WebSocketServer {
	private final static Logger log = LogManager.getLogger(WebSocketServer.class);

	private Session session;
	private String clientId;

	/**
	 * 建立连接成功调用 (Session + 场景)
	 */
	@OnOpen
	public void onOpen(Session session, @PathParam("clientId") String screen) throws IOException {
		this.session = session;
		this.clientId = screen;
		log.info("[onOpen][session({}) 接入, [clientId: {}]", session, clientId);
		WebSocketServerPool.addDataConnect(session, clientId);
		// WebSocketServerPool.sendMessage(session,
		// configurationScreenService.queryAllJsonById(clientId));
	}

	/**
	 * 关闭连接时调用
	 * 
	 * @param session 连接
	 */
	@OnClose
	public void onClose(Session session, CloseReason closeReason) {
		log.info("[onClose][session({}) 连接关闭。关闭原因是({})}]", session, closeReason);
		WebSocketServerPool.removeConnect(session);
	}

	/**
	 * 错误时调用
	 * 
	 * @param session   连接
	 * @param throwable 异常
	 */
	@OnError
	public void onError(Session session, Throwable throwable) {
		log.info("[onClose][session({}) 发生异常]", session, throwable);
		WebSocketServerPool.removeConnect(session);
	}

	/**
	 * 收到客户端信息后，根据接收到的信息进行处理
	 * 
	 * @param session 连接
	 * @param message 数据消息
	 */
	@OnMessage
	public void onMessage(Session session, String message) {
		log.info("[onOpen][session({}) 接收到一条消息({})]", session, message);
		// TODO: 2022/5/18 对于客户端发送的指令信息，解析后进行对应的逻辑处理
	}

	/**
	 * 向客户端发送消息
	 */
	public void sendMessage(String message) throws IOException {
		// this.session.getBasicRemote().sendText(message);
		// this.session.getAsyncRemote().sendText(message);
		ConcurrentMap<Session, String> webSocketMap = WebSocketServerPool.getDataConnect();
		for (Session session : webSocketMap.keySet()) {
			try {
				session.getBasicRemote().sendText(message);
			} catch (IOException e) {
				System.err.println(this + "发送消息错误:" + e.getClass() + ":" + e.getMessage());
			}
		}
	}

	/**
	 * 通过clientId向客户端发送消息
	 */
	public void sendMessageByClientId(String clientId, String message) throws IOException {
		log.info("服务端发送消息到{},消息：{}", clientId, message);
		if (StringUtils.isNotBlank(clientId) && WebSocketServerPool.getDataConnect().containsKey(session)) {
			sendMessage(message);
		} else {
			log.error("用户{}不在线", clientId);
		}
	}

}
